using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using FreeSwitch.EventSocket.Commands;
using FreeSwitch.EventSocket.Parser;

namespace FreeSwitch.EventSocket
{
	public class TestProxy
	{
		private EventChannel _server;
		private List<EventChannel> _clients;
		private TcpListener _listener;
		private string _password;

		private LinkedList<ICommand> _commands = new LinkedList<ICommand>();
		private ManualResetEvent _commandEvent = new ManualResetEvent(false);

		public TestProxy(string password)
		{
			_password = password;
		}
		private class CommandQueueEntry
		{
			ICommand Command { get; set; }
			EventChannel Client { get; set; }
		}

		public void Start(IPEndPoint FreeSwitch, IPEndPoint listener)
		{
			_server = new EventChannel(FreeSwitch);
			_listener = new TcpListener(listener);
			_listener.Start();
			_listener.BeginAcceptSocket(OnAccept, null);
			_server.MessageReceived += OnServerMessage;
			_server.Start();
		}

		private void OnServerMessage(object sender, MessageEventArgs e)
		{
			switch (e.Message.Headers["Content-Type"])
			{
				case "auth/request":
					_server.Send(new Authenticate(_password).ToString());
					break;
				case "text/command":
					ProcessClientCommand(e);
					break;

			}
		}

		private void OnAccept(IAsyncResult ar)
		{
			var socket = _listener.EndAcceptSocket(ar);
			var eventSocket = new ProxyEventSocket(socket) {IsMaster = _clients.Count == 0};
			eventSocket.MessageReceived += OnClientMessage;
			_clients.Add(eventSocket);
			eventSocket.Start();
			eventSocket.Send("Content-Type: auth/request\n\n");

			if (!_server.IsConnected)
				_server.Start();
		}

		private void OnClientMessage(object sender, MessageEventArgs e)
		{
			ProxyEventSocket socket = (ProxyEventSocket)sender;
			switch (e.Message.Headers["Content-Type"])
			{
				case "auth/request":
				if (!socket.IsMaster)
					return;
				_server.Send(new Authenticate(_password).ToString());
					break;
				case "text/command":
					ProcessClientCommand(e);
					break;

			}
		}

		private void ProcessClientCommand(MessageEventArgs args)
		{
		}
	}

	public class ProxyBufferEventArgs : EventArgs
	{
		public ProxyBufferEventArgs(byte[] buffer)
		{
			
		}
	}

	public class ProxyEventSocket : EventChannel
	{
		public ProxyEventSocket(IPEndPoint freeSwitchAddress) : base(freeSwitchAddress)
		{
		}

		public ProxyEventSocket(Socket socket) : base(socket)
		{
		}

		/// <summary>
		/// Gets or sets if socket is master (and should authenticate).
		/// </summary>
		public bool IsMaster { get; set; }
	}
}